package com.starry.core.security.utils;

import cn.hutool.json.JSONUtil;
import com.starry.core.common.domain.R;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.server.resource.authentication.AbstractOAuth2TokenAuthenticationToken;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @Description SecurityErrorUtil
 * @Author xiaoke
 */
@Slf4j
public class SecurityErrorUtil {

    /**
     * 认证与鉴权失败回调
     *
     * @param request  当前请求
     * @param response 当前响应
     * @param e        具体的异常信息
     */
    public static void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Throwable e) {
        R<Void> parameters = getErrorParameter(request, response, e);
        try {
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.getWriter().write(JSONUtil.toJsonStr(parameters));
            response.getWriter().flush();
        } catch (IOException ex) {
            log.error("写回错误信息失败", e);
        }
    }

    /**
     * 获取异常信息map
     *
     * @param request  当前请求
     * @param response 当前响应
     * @param e        本次异常具体的异常实例
     * @return 异常信息map
     */
    public static R<Void> getErrorParameter(HttpServletRequest request, HttpServletResponse response, Throwable e) {
        R<Void> r = new R<>();
        r.setSuccess(false);
        if (request.getUserPrincipal() instanceof AbstractOAuth2TokenAuthenticationToken) {
            // 权限不足
            r.setMsg("权限不足");
            r.setCode(HttpStatus.FORBIDDEN.value());
        }
        if (e instanceof OAuth2AuthenticationException authenticationException) {
            r.setMsg("token无效");
            r.setCode(HttpStatus.UNAUTHORIZED.value());
        }
        if (e instanceof InsufficientAuthenticationException) {
            r.setMsg("缺失token");
            r.setCode(HttpStatus.BAD_REQUEST.value());
        }
        return r;
    }
}
